package com.fingard.dsp.bank.directbank.chinapay01;

import java.util.HashMap;
import java.util.Map;

import com.fingard.constant.Format;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.FailCode;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.bankInterface.ISMSRec;
import com.fingard.dsp.bank.directbank.chinapay01.util.AcpService;
import com.fingard.dsp.bank.reqrespobj.single.ReqQrySingle;
import com.fingard.dsp.bank.reqrespobj.single.RetAtsSingle;
import com.fingard.dsp.bank.reqrespobj.single.detail.RetAtsSglDetail;
import com.fingard.dsp.bank.reqrespobj.smsrec.ReqSMSRec;
import com.fingard.text.StringHelper;

/**
 * 中国银联快捷支付
 * 
 * 接口开发流程: 
 * 	1、发起卡开通状态查询 
 * 		(1)返回已开通，则进入获取验证码阶段; 
 * 		(2)未开通，前端跳转银联网关页面属于开户信息进行开通;
 *  2、开通后发起申请验证码接口; 
 *  3、用户填入验证码后发起消费交易进行短信扣款;
 * 
 * @author Cruise
 * @date 2018/9/21
 */
public class ChinaPay01SMSRec extends ChinaPay01Base implements ISMSRec {
	@Override
	public RetAtsSingle d_9110_SMSRec(ReqSMSRec p_req9110) throws Exception {
		RetAtsSingle retAts = new RetAtsSingle(p_req9110.reqHeader);
		RetAtsSglDetail tmpRetDetail = new RetAtsSglDetail();
		tmpRetDetail.reqSeqID = p_req9110.singleDetail.askNumber;

		try {
			ActSetItem actItem = getBankConfig().getActSetItem(p_req9110.singleDetail.recAct, "smsRec");
			if (actItem != null) {
				if ("01".equals(p_req9110.singleDetail.step)) {
					Map<String, String> mapParams = new HashMap<String, String>();

					mapParams.put("version", "5.1.0");
					mapParams.put("encoding", getCharset());
					mapParams.put("signMethod", "01");
					mapParams.put("txnType", "78");
					mapParams.put("txnSubType", "00");
					mapParams.put("bizType", "000301");
					mapParams.put("accessType", "0");
					mapParams.put("channelType", "07");
					mapParams.put("merId", actItem.merchantId);
					mapParams.put("orderId", p_req9110.singleDetail.askNumber);
					mapParams.put("txnTime", Format.DateTime14Format.format(p_req9110.singleDetail.getPayDateTime()));
					mapParams.put("accNo", encryptData(p_req9110.singleDetail.payAct, getCharset(), actItem));
					mapParams.put("encryptCertId", getEncryptCertId(actItem));

					Map<String, String> rspData = sendToBank(mapParams, actItem, bankFront.getUrl("smsRecSubmit"));

					if (verifySignByRSA(rspData, actItem)) {
						tmpRetDetail.respCode = "0";
						tmpRetDetail.respInfo = rspData.get("respMsg");

						if (("00").equals(rspData.get("respCode"))) {
							WriteBankLogLn2("卡已开通，开始获取验证码......");

							Map<String, String> mapReq = new HashMap<String, String>();
							
							mapReq.put("version", "5.1.0");
							mapReq.put("encoding", getCharset());
							mapReq.put("signMethod", "01");
							mapReq.put("txnType", "77");
							mapReq.put("txnSubType", "02");
							mapReq.put("bizType", "000301");
							mapReq.put("channelType", "07");
							mapReq.put("accessType", "0");
							mapReq.put("merId", actItem.merchantId);
							mapReq.put("accNo", encryptData(p_req9110.singleDetail.payAct, getCharset(), actItem));
							mapReq.put("orderId", p_req9110.singleDetail.askNumber);
							mapReq.put("txnTime", Format.DateTime14Format.format(p_req9110.singleDetail.getPayDateTime()));
							mapReq.put("currencyCode", "156");
							mapReq.put("txnAmt", StringHelper.amountMultiply100(p_req9110.singleDetail.payAmount));
							mapReq.put("encryptCertId", getEncryptCertId(actItem));

							Map<String, String> tmpMapRet = sendToBank(mapReq, actItem, bankFront.getUrl("smsRecSubmit"));

							if (verifySignByRSA(tmpMapRet, actItem)) {
								tmpRetDetail.respCode = "0";
								tmpRetDetail.respInfo = tmpMapRet.get("respMsg");

								String tmpRespCode = tmpMapRet.get("respCode");
								if (("00").equals(tmpRespCode)) {
									tmpRetDetail.respInfo = "已提交";
									tmpRetDetail.transState = PaymentState.SUCCESS;
								} else {
									tmpRetDetail.transState = PaymentState.FAIL;
								}
								tmpRetDetail.payInfoCode = tmpRespCode;
							} else {
								tmpRetDetail.respCode = "-1";
								tmpRetDetail.respInfo = "获取验证码银联响应数据本地验签失败!";
							}
						} else {
							tmpRetDetail.transState = PaymentState.FAIL_Payment;
							tmpRetDetail.payInfoCode = "E1077";
						}
					} else {
						tmpRetDetail.respCode = "-1";
						tmpRetDetail.respInfo = "卡开通查询银联响应数据本地验签失败!";
					}
				} else if ("02".equals(p_req9110.singleDetail.step)) {
					Map<String, String> mapReq = new HashMap<String, String>();

					mapReq.put("version", "5.1.0");
					mapReq.put("encoding", getCharset());
					mapReq.put("signMethod", "01");
					mapReq.put("txnType", "01");
					mapReq.put("txnSubType", "01");
					mapReq.put("bizType", "000301");
					mapReq.put("channelType", "07");
					mapReq.put("backUrl", actItem.notifyURL);
					mapReq.put("accessType", "0");
					mapReq.put("merId", actItem.merchantId);
					mapReq.put("orderId", p_req9110.singleDetail.askNumber);
					mapReq.put("txnTime", Format.DateTime14Format.format(p_req9110.singleDetail.getPayDateTime()));
					mapReq.put("accNo", encryptData(p_req9110.singleDetail.payAct, getCharset(), actItem));
					mapReq.put("txnAmt", StringHelper.amountMultiply100(p_req9110.singleDetail.payAmount));
					mapReq.put("currencyCode", "156");
					mapReq.put("reqReserved", p_req9110.singleDetail.attach);

					Map<String, String> customerInfoMap = new HashMap<String, String>();
					customerInfoMap.put("smsCode", p_req9110.singleDetail.verifyCode);
					String customerInfoStr = AcpService.getCustomerInfoWithEncrypt(customerInfoMap,
							p_req9110.singleDetail.payAct, getCharset());
					mapReq.put("customerInfo", customerInfoStr);
					mapReq.put("encryptCertId", getEncryptCertId(actItem));

					Map<String, String> rspData = sendToBank(mapReq, actItem, bankFront.getUrl("smsRecSubmit"));

					if (verifySignByRSA(rspData, actItem)) {
						tmpRetDetail.respCode = "0";
						tmpRetDetail.respInfo = rspData.get("respMsg");
						tmpRetDetail.transState = rspData.get("respCode");
						tmpRetDetail.payInfoCode = rspData.get("respCode");
						String payAmount = rspData.get("txnAmt");
						if (StringHelper.hasAnyChar(payAmount)) {
							tmpRetDetail.transAmt = StringHelper.amountDivide100(payAmount);
						}

						// 如果快捷扣款返回支付中，则等待指定时间后发起查询
						if ("00".equals(rspData.get("respCode"))) {
							Map<String, String> tmpMapQueryReq = new HashMap<String, String>();
							tmpMapQueryReq.put("RecAct", p_req9110.singleDetail.recAct);
							tmpMapQueryReq.put("BgnDateTime", Format.DateTime14Format.format(p_req9110.singleDetail.getPayDateTime()));
							tmpMapQueryReq.put("AskNumber", p_req9110.singleDetail.askNumber);

							String tmpSleepTimeList = getBankConfig().getValueAsString("sleepTimeList");
							if (tmpSleepTimeList.length() >= 2) {
								String[] tmpSleepTimeArr = tmpSleepTimeList.split(",");
								if (Integer.parseInt(tmpSleepTimeArr[tmpSleepTimeArr.length - 1]) <= 32) {
									String[] realSleepTimeList = getRealSleepTimeList(tmpSleepTimeList);
									int queryCount = 0;
									for (int i = 0; i < realSleepTimeList.length; i++) {
										if (queryCount > 5) {
											break; // 查询次数超过5次，限制查询!
										}
										
										Thread.sleep(Integer.parseInt(realSleepTimeList[i]) * 1000); // 睡眠指定时间后发起查询

										Map<String, String> tmpMapRet = qrySMSRecResult(tmpMapQueryReq);
										if (tmpMapRet.containsKey("origRespCode")) {
											// 有最终状态才更新支付提交状态
											tmpRetDetail.transState = StringHelper.joinNotEmpty("+", tmpMapRet.get("respCode"), tmpMapRet.get("origRespCode"));
											tmpRetDetail.payInfoCode = tmpMapRet.get("origRespCode");
											if (StringHelper.hasAnyChar(tmpMapRet.get("respMsg"))) {
												tmpRetDetail.respInfo = tmpMapRet.get("respMsg");
											}
											if (StringHelper.hasAnyChar(tmpMapRet.get("origRespMsg"))) {
												tmpRetDetail.respInfo = tmpMapRet.get("origRespMsg");
											}
											break;
										}
										queryCount++;
									}
								}
							}
						}
					} else {
						tmpRetDetail.respCode = "-1";
						tmpRetDetail.respInfo = "验证码提交扣款银联响应数据本地验签失败!";
					}
				} else {
					tmpRetDetail.respCode = "0";
					tmpRetDetail.respInfo = "未能识别的step：" + p_req9110.singleDetail.step;
					tmpRetDetail.transState = PaymentState.FAIL_Payment;
					tmpRetDetail.payInfoCode = FailCode.E9981;
				}
			} else {
				tmpRetDetail.respCode = "0";
				tmpRetDetail.respInfo = "未找到账号[" + p_req9110.singleDetail.recAct + "]商户配置信息!";
				tmpRetDetail.transState = PaymentState.FAIL_Payment;
				tmpRetDetail.payInfoCode = FailCode.E9981;
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			tmpRetDetail.respCode = "-1";
			tmpRetDetail.respInfo = ex.getMessage();
			WriteBankLogLn(ex);
		}

		retAts.writeRetDetail(tmpRetDetail);
		return retAts;
	}

	public Map<String, String> qrySMSRecResult(Map<String, String> p_req9146) throws Exception {
		Map<String, String> tmpMapRet = new HashMap<String, String>();

		try {
			ActSetItem actItem = getBankConfig().getActSetItem(p_req9146.get("RecAct"), "smsRec");
			if (actItem != null) {
				HashMap<String, String> mapParams = new HashMap<String, String>();

				mapParams.put("version", "5.1.0");
				mapParams.put("encoding", getCharset());
				mapParams.put("signMethod", "01");
				mapParams.put("txnType", "00");
				mapParams.put("txnSubType", "00");
				mapParams.put("bizType", "000301");
				mapParams.put("accessType", "0");
				mapParams.put("merId", actItem.merchantId);
				mapParams.put("txnTime", p_req9146.get("BgnDateTime"));
				mapParams.put("orderId", p_req9146.get("AskNumber"));

				Map<String, String> rspData = sendToBank(mapParams, actItem, bankFront.getUrl("smsRecQuery"));

				if (verifySignByRSA(rspData, actItem)) {
					String tmpRespCode = rspData.get("respCode");
					if (("00").equals(tmpRespCode)) {
						String oriRespCode = rspData.get("origRespCode");
						if (!"05".equals(oriRespCode)) {
							tmpMapRet = rspData;
							return tmpMapRet;
						}
					} else {
						tmpMapRet.put("RespCode", "-1");
						tmpMapRet.put("RespInfo", rspData.get("respMsg"));
					}
				} else {
					tmpMapRet.put("RespCode", "-1");
					tmpMapRet.put("RespInfo", "快捷支付查询银联响应数据本地验签失败!");
				}
			} else {
				tmpMapRet.put("RespCode", "-1");
				tmpMapRet.put("RespInfo", "未找到账号:[" + p_req9146.get("RecAct") + "]商户配置信息!");
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			tmpMapRet.put("RespCode", "-1");
			tmpMapRet.put("RespInfo", ex.getMessage());
			WriteBankLogLn(ex);
		}

		return tmpMapRet;
	}

	@Override
	public RetAtsSingle d_9146_QrySMSRec(ReqQrySingle p_req9146) throws Exception {
		RetAtsSingle retAts = new RetAtsSingle(p_req9146.reqHeader);
		RetAtsSglDetail tmpRetDetail = new RetAtsSglDetail();
		tmpRetDetail.reqSeqID = p_req9146.askNumber;

		try {
			ActSetItem actItem = getBankConfig().getActSetItem(p_req9146.recAct, "smsRec");
			if (actItem != null) {
				HashMap<String, String> mapParams = new HashMap<String, String>();

				mapParams.put("version", "5.1.0");
				mapParams.put("encoding", getCharset());
				mapParams.put("signMethod", "01");
				mapParams.put("txnType", "00");
				mapParams.put("txnSubType", "00");
				mapParams.put("bizType", "000301");
				mapParams.put("accessType", "0");
				mapParams.put("merId", actItem.merchantId);
				mapParams.put("txnTime", Format.DateTime14Format.format(p_req9146.getBgnDateTime()));
				mapParams.put("orderId", p_req9146.askNumber);

				Map<String, String> rspData = sendToBank(mapParams, actItem, bankFront.getUrl("smsRecQuery"));

				if (verifySignByRSA(rspData, actItem)) {
					tmpRetDetail.respCode = "0";
					tmpRetDetail.respInfo = rspData.get("respMsg");

					String tmpRespCode = rspData.get("respCode");
					if (("00").equals(tmpRespCode) || "34".equals(tmpRespCode)) {
						String tmpRespInfo = rspData.get("origRespMsg");
						if (StringHelper.hasAnyChar(tmpRespInfo)) {
							tmpRetDetail.respInfo = tmpRespInfo;
						}
						
						tmpRetDetail.transState = StringHelper.joinNotEmpty("+", tmpRespCode, rspData.get("origRespCode"));
						tmpRetDetail.payInfoCode = rspData.get("origRespCode");

						if ("34".equals(tmpRespCode)) {
							if (canBeNotExist(p_req9146, tmpRetDetail, 10)) { // 10分钟后查询还是查无此交易则置为支付失败
								tmpRetDetail.transState = tmpRespCode;
								tmpRetDetail.payInfoCode = tmpRespCode;
							}
						}

						String payAmount = rspData.get("txnAmt");
						if (StringHelper.hasAnyChar(payAmount)) {
							tmpRetDetail.transAmt = StringHelper.amountDivide100(payAmount);
						}
					} else {
						tmpRetDetail.respCode = "-1";
						tmpRetDetail.respInfo = rspData.get("respMsg");
					}
				} else {
					tmpRetDetail.respCode = "-1";
					tmpRetDetail.respInfo = "快捷支付查询银联响应数据本地验签失败!";
				}
			} else {
				tmpRetDetail.respCode = "-1";
				tmpRetDetail.respInfo = "未找到账号[" + p_req9146.recAct + "]商户配置信息!";
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			tmpRetDetail.respCode = "-1";
			tmpRetDetail.respInfo = ex.getMessage();
			WriteBankLogLn(ex);
		}

		retAts.writeRetDetail(tmpRetDetail);
		return retAts;
	}
}
